﻿using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using EPiServer.DataAbstraction;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using EPiServer.Core;
using EPiSugar.UnitTesting;
using EPiSugar.Navigation;
using System;

namespace EPiSugar.Tests.Navigation
{
    [TestFixture]
    public class PageDataTests : NavigationTestsBase
    {
        [Test]
        public void CanRetrieve_DefaultPages()
        {
            Assert.That(rootPage.PageLink, Is.EqualTo(PageReference.RootPage));
            Assert.That(wasteBasket.PageLink, Is.EqualTo(PageReference.WasteBasket));
            Assert.That(startPage.PageLink, Is.EqualTo(PageReference.StartPage));
        }

        [Test]
        public void CanGetChildren_OfStartPageData()
        {
            Assert.That(startPage.Children().Count(), Is.EqualTo(3));
        }

        [Test]
        public void CanGetFirstBornChild_OfRootPage()
        {
            PageData first = rootPage.Children().ElementAt(0);
            Assert.That(first, Is.EqualTo(wasteBasket));
        }

        [Test]
        public void CanGetSecondBornChild_OfRootPage()
        {
            PageData second = rootPage.Children().ElementAt(1);
            Assert.That(second, Is.EqualTo(startPage));
        }

        [Test]
        public void CanGetParent_OfStartPage()
        {
            PageData parent = startPage.Parent();
            Assert.That(parent, Is.EqualTo(rootPage));
        }

        [Test]
        public void CanGetAncestors_OfRootPage()
        {
            int count = startPage.Ancestors().Count();
            Assert.That(count, Is.EqualTo(1));
        }

        [Test]
        public void CanGetAncestors_OfStartPage()
        {
            int count = rootPage.Ancestors().Count();
            Assert.That(count, Is.EqualTo(0));
        }

        [Test]
        public void GetAncestors_UntilItself_YieldsNone()
        {
            int count = startPage.Ancestors(startPage.PageLink).Count();
            Assert.That(count, Is.EqualTo(0));
        }

        [Test]
        public void CanGetAncestors_OfYougestNephew()
        {
            PageData page = startPage.Children().Last().Children().Last();
            int count = page.Ancestors().Count();
            Assert.That(count, Is.EqualTo(3));
        }

        [Test]
        public void CanGetAncestors_UntilStartPage_OfYougestNephew()
        {
            PageData page = startPage.Children().Last().Children().Last();
            int count = page.Ancestors(PageReference.RootPage).Count();
            Assert.That(count, Is.EqualTo(2));
        }

        [Test]
        public void CanGetDescendants_OfStartPage()
        {
            Assert.That(startPage.Descendants().Count(), Is.EqualTo(12));
        }

        [Test]
        public void Descendants_AreExplored_DepthFirst()
        {
            var list = new PageDataCollection(startPage.Descendants());
            Assert.That(list[0], Is.EqualTo(startPage.Children().First()), "First child of start page was not first.");
            Assert.That(list[1].Parent(), Is.EqualTo(list[0]), "Did not recurse into first child tree");
            Assert.That(list[11].Parent(), Is.EqualTo(startPage.Children().ElementAt(2)), "Expected parent of last element to be last child of start page");
        }

        [Test]
        public void CanGetDescendants_UntilDepth()
        {
            int count = startPage.Descendants(1).Count();
            Assert.That(count, Is.EqualTo(width));
        }

        [Test]
        public void CanGetDescendants_UntilDepth2()
        {
            int count = startPage.Descendants(2).Count();
            Assert.That(count, Is.EqualTo(width * width + width));
        }

        [Test]
        public void CanGetDescendants_WithoutDepth()
        {
            int count = startPage.Descendants(0).Count();
            Assert.That(count, Is.EqualTo(0));
        }

        [Test]
        public void SiblingsOfPage_IncludesThePageItself()
        {
            var sibling = GetSiblingAtIndex(1);
            int count = sibling.Siblings().Count();
            Assert.That(count, Is.EqualTo(3));
        }

        [Test]
        public void PrecedingSiblings_DoesNotInclude_SubsequentPages()
        {
            var sibling = GetSiblingAtIndex(1);
            var preceding = sibling.PrecedingSiblings();
            
            Assert.That(preceding.Count(), Is.EqualTo(1));
            Assert.That(preceding.First(), Is.EqualTo(GetSiblingAtIndex(0)));
        }

        [Test]
        public void SuccessiveSiblings_DoesNotInclude_PrecedingPages()
        {
            var sibling = GetSiblingAtIndex(1);
            var successive = sibling.SubsequentSiblings();

            Assert.That(successive.Count(), Is.EqualTo(1));
            Assert.That(successive.First(), Is.EqualTo(GetSiblingAtIndex(2)));
        }

        private PageData GetSiblingAtIndex(int index)
        {
            return startPage.Children().ElementAt(index);
        }
    }
}